#
#   Copyright 2010 Matthew Crinklaw-Vogt
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#  limitations under the License.
#

from genshi.builder import tag
from genshi.core import TEXT
from genshi.filters import Transformer
from genshi.input import HTML
from trac.core import *
from trac.ticket.model import Ticket
from trac.web import IRequestHandler
from trac.web.api import ITemplateStreamFilter
from genshi.template import TemplateLoader
from trac.web.chrome import add_stylesheet, ITemplateProvider
import os, sys, traceback

import pyxchange
import urllib
from trac.web.href import Href

def error(): 
    tb = traceback.format_exception(sys.exc_info()[0],sys.exc_info()[1],sys.exc_info()[2]) 
    return tb[len(tb)-1].replace('\n','')

# TODO: write basic state to a flat file?
# sessions?  cookies?
class StackTracPlugin(Component):
    implements(ITemplateStreamFilter, IRequestHandler, ITemplateProvider)
    
    def get_htdocs_dirs(self):
        from pkg_resources import resource_filename
        return [('se', resource_filename(__name__, 'htdocs'))]
    
    def get_templates_dirs(self):
        from pkg_resources import resource_filename
        return [resource_filename(__name__, 'htdocs/html')]
    
    # TODO: how do we get
    # info about tickets?  Like query for keywords and stuffs?
    # and ticket title/name?
    def filter_stream(self, req, method, filename, stream, data):
        if req.path_info.startswith('/ticket'):
            add_stylesheet(req, 'se/css/style.css')
            ticket = Ticket(self.env, req.args['id'])
            
            imgSrc = Href(req.base_path).chrome('se/images/ajax-loader.gif')
            stream = stream | Transformer('//div[@id="ticket"]').after(
                tag.div(
                    tag.h3('Stack Exchange', class_='foldable collapsed'),
                    tag.div(tag.center(tag.img(src=imgSrc)), id='exchange-content', style='border: 1px outset #996; padding: 1em')))
            
            stream = stream | Transformer('head').append(
                tag.script('$(document).ready(function() { updateExchange(false, false, "' 
                           + self._getKeywords(ticket['keywords']) + '", "' + ticket['summary'] + '"); });', 
                           type='text/javascript'))
            
            # TODO: can I drop this into some js file and include it
            # easily?  Any way to modify the existing template
            # w/o using a filter?
            stream = stream | Transformer('head').append(
                tag.script(
                '''
                function updateExchange(byKeyword, byDesc, keywords, desc) {
                    jQuery.get("../stackexchange",
                     { bykw: byKeyword,
                       bysmry: byDesc,
                       kws: keywords,
                       smry: desc },
                    updateExchangeCB);
                }
                
                function updateExchangeCB(ajaxResult) {
                    jQuery("#exchange-content").html(ajaxResult);
                }
                '''))
        
        return stream
    
    # TODO: need to do something if semicolon is already contained in the KWords...
    def _getKeywords(self, pKeywords):
        return pKeywords.replace(' ', '; ')
    
    # IRequestHandler methods
    def match_request(self, req):
        return req.path_info.startswith('/stackexchange')

    # handles ajax requests from component...
    def process_request(self, req):
        
        try:
            # 'http://api.stackoverflow.com/1.0/'
            finder = QuestionFinder(req.args['smry'], self.config.get('stacktrac', 'apiSite') + '/')
            questions = finder.getQuestions()
            response = StackExchangePresenter(questions, self.config.get('stacktrac', 'site') + '/').format()
           # sexResult = stackExchange.search().pagesize(5).tagged(req.args['kws']).key('ggsT3feHTU6rEQjeoNe9DA').execute()
           # response = StackExchangePresenter(sexResult, 'http://www.stackoverflow.com/').format()
        except:
            response = 'err: ' + error()
        req.send_response(200)
        req.send_header('Content-Type', 'text/plain')
        req.send_header('Content-Length', len(response))
        req.end_headers()
        req.write(response)

templateLoader = TemplateLoader(
    os.path.join(os.path.dirname(__file__), 'htdocs/html'),
    auto_reload=True
)

class QuestionFinder:
    def __init__(self, pTicketSummary, pSEApiSite):
        self.ticketSummary = pTicketSummary
        self.seApiSite = pSEApiSite
    
    def getQuestions(self):
        questions = []
        
        questionIDs = self._getQuestionIDsUsingGoogle()
        
        for id in questionIDs:
            questions.append(self._getQuestionInfo(id))
        return questions
    
    def _getQuestionIDsUsingGoogle(self):
        questionIDs = []
        #lol @ this :)
        pyxAsGoogle = pyxchange.PyXchange('http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=site:stackoverflow.com%20'
                                    + urllib.quote(self.ticketSummary) + '&key=ABQIAAAASYhIY2Ob7eyX69lzM7waKRR_gY0w0Dm1rDLT-ZWUMIHpsHSAsRQRXIT2SwS6K7sVau_QkRqNIc5-7Q')
        googleResult = pyxAsGoogle.execute();
        
        for result in googleResult['responseData']['results']:
            questionID = self._getQuestionIDFromGoogleResult(result)
            if questionID != -1:
                questionIDs.append(questionID);
        return questionIDs
    
    def _getQuestionIDFromGoogleResult(self, pResult):
        url = pResult['url']
        components = url.split('/')
        
        if components[3] == 'questions':
            return int(components[4].__str__())
        
        return -1
    
    def _getQuestionInfo(self, pQuestionID):
        stackExResult = pyxchange.PyXchange(self.seApiSite).questions(pQuestionID).execute()
        return stackExResult['questions'][0]

class StackExchangePresenter:
    def __init__(self, pStackExchangeResponse, pStackSite):
        self.stackExchangeContent = pStackExchangeResponse
        self.stackSite = pStackSite
        # TODO: parse the response into something pretty...
    
    def format(self):
        tmpl = templateLoader.load('stackExchangeResponse.html')
        return tmpl.generate(questions=self.stackExchangeContent, stackSite=self.stackSite).render('html')

        